package com.module.zk;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import lombok.Getter;
import lombok.Setter;

public class ZookeeperClient {
    private static final Logger logger = LoggerFactory.getLogger(ZookeeperClient.class);

    private static final int SLEEP_TIME_MS = 1000;
    private static final int MAX_RETRIES = 3;

//    @Setter @Getter
    private String zookeeperServer;

//    @Setter @Getter
    private String zookeeperLockPath;

    public ZookeeperClient(String zookeeperServer, String zookeeperLockPath) {
        this.zookeeperServer = zookeeperServer;
        this.zookeeperLockPath = zookeeperLockPath;
    }

    @Getter
    private CuratorFramework client;

    public <T> T lock(AbstractZookeeperLock<T> mutex) {
        String path = zookeeperLockPath + mutex.getLockPath();
        System.out.println("——————————————"+path+"——————————");
        InterProcessMutex lock = new InterProcessMutex(this.getClient(), path);
        boolean success = false;
        try {
            try {
            	//建锁
                success = lock.acquire(mutex.getTimeout(), mutex.getTimeUnit());
            } catch (Exception e) {
                throw new RuntimeException("obtain lock error " + e.getMessage() + ", path " + path);
            }
            if (success) {
                return (T) mutex.execute();
            } else {
                return null;
            }
        } finally {
            try {
                if (success){
                	//释放锁
                    lock.release();
                }
            } catch (Exception e) {
                logger.error("release lock error {}, path {}", e.getMessage(), path);
            }
        }
    }

    /**
     * 初始化curator客户端 连接zk服务器
     * @author chenluqiang
     * @date 2019年3月5日 下午4:08:17
     */
    public void init() {
        this.client = CuratorFrameworkFactory.builder().connectString
        		(zookeeperServer).retryPolicy(new ExponentialBackoffRetry(SLEEP_TIME_MS, MAX_RETRIES)).build();
        this.client.start();
    }
    
    /**
     * 关闭curator客户端 与zk服务器连接
     * @author chenluqiang
     * @date 2019年3月5日 下午4:11:16
     */
    public void destroy() {
        try {
            if (getClient() != null) {
                getClient().close();
            }
        } catch (Exception e) {
            logger.error("stop zookeeper client error {}", e.getMessage());
        }
    }
}
